package net.lummox.model;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Locale;

import org.apache.log4j.Logger;

public abstract class CommonDaoImpl<T extends Entity> implements CommonDao<T> {

	private final String DELETE_QUERY = "delete from %s where id = :id";

	protected abstract String getSelectSql();
	protected abstract String getSelectAllSql();
    protected abstract String getInsertSql();
    protected abstract String getUpdateSql();

    protected abstract T createModelFromResultSet(ResultSet rs);
    
	@Override
	public abstract int insert(T t);

	@Override
	public abstract boolean update(T t);

	@Override
	public abstract T getById(int id);

	@Override
	public abstract List<T> getAll();

	public CommonDaoImpl() {
		try {
			Locale.setDefault(Locale.ENGLISH);
			Class.forName("oracle.jdbc.OracleDriver");
			connection = DriverManager
					.getConnection("jdbc:oracle:thin:lummox/lummox@winxp:1521:xe");

		} catch (ClassNotFoundException e) {
			logger.error(e);
		} catch (SQLException e) {
			logger.error(e);
		}
	}

	@Override
	public boolean delete(int Id) {

		int delCount = 0;

		if (null == deleteStatement) {
			createDeleteStatement();
		}

		try {
			deleteStatement.setInt(1, Id);
			delCount = deleteStatement.executeUpdate();
		} catch (SQLException e) {
			logger.error(e);
		}

		return (delCount > 0);
	}

	protected void createSelectStatement() {

		try {
			selectStatement = connection.prepareStatement(getSelectSql());
		} catch (SQLException e) {
			logger.error(e);
		}

	}

	protected void createDeleteStatement() {
		try {
			String deleteQuery = String.format(DELETE_QUERY, type.getSimpleName());
			deleteStatement = connection.prepareStatement(deleteQuery);
		} catch (SQLException e) {
			logger.error(e);
		}
	}

	protected void createSelectAllStatement() {

		try {
			selectAllStatement = connection.prepareStatement(getSelectAllSql());
		} catch (SQLException e) {
			logger.error(e);
		}

	}

	protected void createInsertStatement() {
		
		try {		
			insertStatement = connection.prepareCall(getInsertSql());
		} catch (SQLException e) {
			logger.error(e);
		}
		
	}

	protected void createUpdateStatement() {		
		try {		
			updateStatement = connection.prepareCall(getUpdateSql());
		} catch (SQLException e) {
			logger.error(e);
		}		
	}

	protected PreparedStatement getSelectStatement(int id) {

		if (null == selectStatement) {
			createSelectStatement();
		}

		try {

			selectStatement.setInt(1, id);

		} catch (SQLException e) {
			logger.error(e);
		}
		return selectStatement;
	}

	protected PreparedStatement getSelectAllStatement() {

		if (null == selectAllStatement) {
			createSelectAllStatement();
		}

		return selectAllStatement;
	}

	protected CallableStatement getInsertStatement() {

		if (null == insertStatement) {
			createInsertStatement();
		}

		return insertStatement;
	}
	
	protected CallableStatement getUpdateStatement() {

		if (null == updateStatement) {
			createUpdateStatement();
		}

		return updateStatement;
	}
	
	protected Connection connection;
	private PreparedStatement selectStatement;
	private PreparedStatement selectAllStatement;
	private PreparedStatement deleteStatement;
	private CallableStatement insertStatement;
	private CallableStatement updateStatement;

	protected Class<T> type;

	private Logger logger = Logger.getLogger(CommonDaoImpl.class);
}
